import 'dart:math';

import 'package:flutter/material.dart';

import 'ArrayCache.dart';
import 'EqGridView.dart';
import 'Equtil.dart';
import 'Paint.dart';
import 'RectF.dart';
import 'DrawFunction.dart';
import 'dart:ui' as ui;

class EqView extends EqGridView {
  final MAXIDITME = 31;

  final XOVERNUMBER = 60;
  late List<Color> eqColors;
  late int ch;
  late Paint paintDot;
  late Paint paintGray;
  late Paint paintLRX;
  late Paint paintRed;
  late int rectR;
  bool? DrawLRX;
  late List<bool> boolean_peq;
  List<bool>? boolean_xover;
  int drawI = 0;
  late List<double> fline_all;
  late List<List<double>> fline_peq;
  late List<List<double>> fline_xover;
  List<double>? line_all;
  List<List<double>>? line_peq;

  late List<List<double>> line_xover; //add by YB 0818

  List<double>? mEq;
  late List<double> mFreq;
  late List<double> mq;
  late int peqLength;
  late List<RectF> rect_peq;
  late List<RectF> rect_xover;

  List<double>? mXover;
  late List<double> mXoverType;

  int width = 0;
  Size size = Size(0, 0);
  late ui.Paint uipaintGrey;
  late ui.Paint uipaintRed;

  bool setNeedsDisplay = true;

  void initData() {
    eqColors = [
      Colors.red,
      Colors.blue,
      Colors.green,
      Colors.cyan,
      Colors.yellow,
      Colors.white,
      Colors.teal,
      Colors.deepOrange,
      Colors.orange,
      Colors.purple,
      Colors.brown
    ];
    this.rectR = 20;
  }

  void initPaint() {
    this.paintRed = Paint();
    this.paintRed.color = Colors.red;
    this.paintRed.strokeWidth = 3;

    this.paintGray = Paint();
    this.paintGray.color = Colors.grey;
    this.paintGray.strokeWidth = 2;

    this.paintDot = Paint();
    this.paintDot.color = Colors.black;
    this.paintDot.strokeWidth = 2;
    this.paintDot.textSize = 24;

    this.paintLRX = Paint();
    this.paintLRX.color = Colors.white;
    this.paintLRX.strokeWidth = 10;
    this.paintLRX.textSize = 60;
    this.paintLRX.alpha = 187 / 255.0;

    //add by ts
    this.uipaintGrey = ui.Paint()..color = paintGray.color;
    uipaintGrey.strokeWidth = paintGray.strokeWidth;
    uipaintGrey
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round;
    uipaintGrey..strokeJoin = StrokeJoin.round;

    this.uipaintRed = ui.Paint()..color = paintRed.color;
    uipaintRed.strokeWidth = paintRed.strokeWidth;
    uipaintRed
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round;
    uipaintRed..strokeJoin = StrokeJoin.round;
  }

  EqView({super.repaint}) {
    initData();
    initPaint();
  }

  void setColor(int index) {
    this.paintRed.color = eqColors[index];
  }

  void colOverlay() {
    if (this.line_all != null) {
      for (int idx = 0; idx < this.line_all!.length; ++idx) {
        this.line_all![idx] = 0.0;
      }
      List tmpArray = this.line_all!;
      for (int index = 0; index < this.peqLength; ++index) {
        for (int j = 0; j < this.line_all!.length; ++j) {
          if (this.line_peq != null &&
              this.line_peq!.length > index &&
              this.line_peq![index] != null &&
              this.line_peq![index].length > j) {
            tmpArray[j] = tmpArray[j] + this.line_peq![index][j];
          }
        }
      }
      /*xover start*/
      if (this.mXover != null) {
//            double[] var5;
        List<double> var5;
        for (int i = 0; i < this.mXover!.length; ++i) {
          for (int j = 0; j < this.line_all!.length; ++j) {
            var5 = this.line_all!;
            //                    var5[j] += this.line_xover[i][j];
            var5[j] = var5[j] + this.line_xover[i][j];
          }
        }
      }

      /*xover end*/

//        [Equtil double2float:this.times var1:this.mTop + (this.mBottom - this.mTop) / 2 var2:this.line_all var3:30 var4:this.fline_all];
      Equtil.double2float(
          this.times,
          (this.mTop + (this.mBottom - this.mTop) / 2).toInt(),
          this.line_all ?? [],
          30,
          this.fline_all);
    }
  }

  void colPEQ(int width) {
    if (this.line_peq != null) {
      for (int index = 0; index < this.peqLength; ++index) {
        colPEQ2(index, width);
      }
    }
  }

  void colPEQ2(int eqIndex, int width) {
    if (this.line_peq?[eqIndex] != null && (this.line_peq?.length ?? 0) > 0) {
      int height = this.mBottom - this.mTop;
      Equtil.cal_point_peq(this.mq[eqIndex], this.mEq![eqIndex],
          this.mFreq[eqIndex].toInt(), this.line_peq![eqIndex]);
//        EqUtil.cal_point_peq(mq[eqIndex], this.mEq[eqIndex], mFreq[eqIndex], this.line_peq[eqIndex]);
      Equtil.double2float(this.times, (this.mTop + height / 2).toInt(),
          this.line_peq![eqIndex], 30, this.fline_peq[eqIndex]);
//        EqUtil.double2float(this.times, this.mTop + height / 2, this.line_peq[eqIndex], 60, this.fline_peq[eqIndex]);
      Equtil.cal_rect(
          this.rect_peq[eqIndex],
          10,
          this.mEq![eqIndex].toInt(),
          this.mFreq[eqIndex].toInt(),
          width - 30 - 10,
          height,
          30,
          this.mTop,
          18);
//        EqUtil.cal_rect(this.rect_peq[eqIndex], 20, this.mEq[eqIndex], mFreq[eqIndex], width - 60 - 20, height, 60, this.mTop, 18);
    }
  }

  void drawLines(Canvas canvas, Size rect) {
    if (this.mEq != null && this.drawI != null) {
      //Rect var5 = new Rect();
      if (this.drawI >= this.peqLength &&
          this.drawI - this.peqLength > this.boolean_xover!.length - 1) {
        this.drawI = 0;
      }

      int var4;
      var path = Path();
      if (this.drawI < this.peqLength) {
        if (this.boolean_peq[this.drawI]) {
          for (int i = 0; i < this.fline_peq[this.drawI].length; i += 4) {
            // print('i--->${this.fline_peq[this.drawI][i + 1]}');
            path.moveTo(this.fline_peq[this.drawI][i],
                this.fline_peq[this.drawI][i + 1]);
            path.lineTo(this.fline_peq[this.drawI][i + 2],
                this.fline_peq[this.drawI][i + 3]);
          }
//                canvas.drawLines(this.fline_peq[this.drawI], paintGray);
        }
      } else {
        var4 = this.drawI - this.peqLength;
        if (this.boolean_xover![var4]) {
          for (int i = 0; i < this.fline_xover[var4].length; i += 4) {
            // print('e------>${this.fline_xover[var4][i + 1]}');
            path.moveTo(
                this.fline_xover[var4][i], this.fline_xover[var4][i + 1]);
            path.lineTo(
                this.fline_xover[var4][i + 2], this.fline_xover[var4][i + 3]);
          }
//                canvas.drawLines(this.fline_xover[var4], paintGray);
        }
      }

      canvas.drawPath(path, this.uipaintGrey);

      path.reset();
      for (int i = 0; i < this.fline_all.length; i += 4) {
        if (this.fline_all[i + 1] > this.mHeight - 20)
          continue; //mark: ts防止曲线出界
        path.moveTo(this.fline_all[i], this.fline_all[i + 1]);
        path.lineTo(this.fline_all[i + 2], this.fline_all[i + 3]);
      }
      this.uipaintRed.color = paintRed.color;
      canvas.drawPath(path, this.uipaintRed);
//        canvas.drawLines(this.fline_all, paintRed);
    }
  }

  bool reArray1(int w) {
    bool rst = true;
    if (this.line_peq != null && w >= 1) {
      int width = w - 30 - 10;

//        this.line_all = [];
//        for (int i=0; i<width; i++) {
//            [this.line_all.add(0];
//        }
      this.line_all = ArrayCache.getEmptyArray(width, 0);

//        this.fline_all = [List arrayWithCapacity:width*4];
//        for (int i=0; i<width*4; i++) {
//            [this.fline_all.add(0];
//        }
      this.fline_all = ArrayCache.getEmptyArray(width * 4, 0);

      this.line_xover = [];
      this.fline_xover = [];

      for (w = 0; w < this.line_peq!.length; w++) {
//            this.line_peq[w] = [];
//            for (int i=0; i<width; i++) {
//                [this.line_peq[w].add(0];
//            }
        this.line_peq![w] = ArrayCache.getEmptyArray(width, 0);

//            this.fline_peq[w] = [List arrayWithCapacity:width*4];
//            for (int i=0; i<width*4; i++) {
//                [this.fline_peq[w].add(0];
//            }
        this.fline_peq[w] = ArrayCache.getEmptyArray(width * 4, 0);

//            this.line_xover[w] = [];
//            for (int i=0; i<width; i++) {
//                [this.line_xover[w].add(0];
//            }
        this.line_xover.add(ArrayCache.getEmptyArray(width, 0));

//            this.fline_xover[w] = [List arrayWithCapacity:width*4];
//            for (int i=0; i<width*4; i++) {
//                [this.fline_xover[w].add(0];
//            }
        this.fline_xover.add(ArrayCache.getEmptyArray(width * 4, 0));
      }
      if (this.boolean_xover != null &&
          this.boolean_xover!.length > 0 &&
          this.boolean_xover![0]) {
        for (int i = 0; i < this.line_xover.length; i++) {
          this.line_xover[i] = [];
          for (int j = 0; j < width; j++) {
            this.line_xover[i].add(0);
          }
          this.fline_xover[i] = [];
          for (int j = 0; j < width * 4; j++) {
            this.fline_xover[i].add(0);
          }
        }
        //                this.line_xover = [ArrayCache getEmptyTwoArray:(int)this.line_xover.length col:width defaultValue:0];
        //                this.fline_xover = [ArrayCache getEmptyTwoArray:(int)this.line_xover.length col:width*4 defaultValue:0];
      }
    } else {
      rst = false;
    }
    return rst;
  }

/*
- (bool)reArray:(int)w
{
    bool rst = YES;
    if (this.line_peq != null && w >= 1) {
        int width = w - 30 - 10;
        
        this.line_all = [];
        for (int i=0; i<width; i++) {
            [this.line_all.add(0];
        }
        
        this.fline_all = [List arrayWithCapacity:width*4];
        for (int i=0; i<width*4; i++) {
            [this.fline_all.add(0];
        }
        
        for (w = 0; w < this.line_peq.length; ++w) {
            this.line_peq[w] = [];
            for (int i=0; i<width; i++) {
                [this.line_peq[w].add(0];
            }
            this.fline_peq[w] = [List arrayWithCapacity:width*4];
            for (int i=0; i<width*4; i++) {
                [this.fline_peq[w].add(0];
            }
            
            this.line_xover[w] = [];
            for (int i=0; i<width; i++) {
                [this.line_xover[w].add(0];
            }
            this.fline_xover[w] = [List arrayWithCapacity:width*4];
            for (int i=0; i<width*4; i++) {
                [this.fline_xover[w].add(0];
            }
            
            
            if (this.boolean_xover.length&& [this.boolean_xover[0] boolValue]) {
                kStartTime
                for (int i = 0; i<this.line_xover.length; i++) {
                    this.line_xover[i] = [];
                    for (int j = 0; j<width; j++) {
                        [this.line_xover[i].add(0];
                    }
                    this.fline_xover[i] = [List arrayWithCapacity:width*4];
                    for (int j = 0; j<width*4; j++) {
                        [this.fline_xover[i].add(0];
                    }
                }
                kEndTime
            }
            
        }
        
    } else {
        rst = NO;
    }
    return rst;
}
*/

  @override
  void paint(Canvas canvas, Size size) {
    super.paint(canvas, size);
    canvas.clipRect(
        Rect.fromLTWH(0, 0, size.width, size.height)); //限制绘制区域，否则会超出size的范围
    this.size = size;
    this.width = size.width.toInt();

    this.times = -0.5555556 * (this.mBottom - this.mTop);
    reArray1(size.width.toInt());
    colPEQ(size.width.toInt());
    colXover(size.width.toInt());
    colOverlay();
    drawLines(canvas, size);

    setNeedsDisplay = false;
  }

  @override
  bool shouldRepaint(EqView oldDelegate) {
    return true;
  }

  void reArray() {
    if (reArray1(this.size.width.toInt())) {
      refreshPEQ();
      refreshXover();
    }
  }

  void reXover() {
    if (reArray1(this.size.width.toInt())) {
      colPEQ2(0, this.size.width.toInt());
      refreshXover();
    }
  }

  void refreshPEQ() {
    for (int var1 = 0; var1 < this.peqLength; ++var1) {
      colPEQ2(var1, this.size.width.toInt());
    }
    colOverlay();
//    this.invalidate();
    setNeedsDisplay = true;
  }

  void refreshPEQ1(int index) {
    this.drawI = index;
    colPEQ2(index, this.size.width.toInt());
    colOverlay();
//    this.invalidate();
    setNeedsDisplay = true;
  }

  void resetPEQ(List<double> q, List<double> eq, List<double> freq) {
    this.mEq = eq;
    this.mq = q;
    this.mFreq = freq;
    refreshPEQ();
  }

  void setPEQ(List<double> q, List<double> eq, List<double> freq,
      {int width = 0}) {
    this.mEq = eq;
    this.mq = q;
    this.mFreq = freq;
    this.peqLength = eq.length;
    this.width = max(this.width, width);
//    this.line_peq = new double[eq.length][];
    this.line_peq = [];
    for (int i = 0; i < eq.length; i++) {
      this.line_peq?.add([]);
    }
    for (int j = 0; j < 8; j++) {
      this.line_peq?[j].add(0);
    }
//    this.fline_peq = new float[eq.length][];
    this.fline_peq = [];
    for (int i = 0; i < eq.length; i++) {
      this.fline_peq.add([]);
    }
    for (int j = 0; j < 8; j++) {
      this.fline_peq[j].add(0);
    }

    /**********************start************************/
    this.line_xover = [];
    for (int i = 0; i < 2; i++) {
      this.line_xover.add([]);
      for (int j = 0; j < this.width / 4; j++) {
        this.line_xover[i].add(0);
      }
    }

    //    this.fline_peq = new float[eq.length][];
    this.fline_xover = [];
    for (int i = 0; i < 2; i++) {
      this.fline_xover.add([]);
      for (int j = 0; j < this.width / 4; j++) {
        this.fline_xover[i].add(0);
      }
    }
    /**********************end************************/

//    this.boolean_peq = new boolean[eq.length];
    this.boolean_peq = [];
    for (int i = 0; i < eq.length; i++) {
      this.boolean_peq.add(false);
    }
//    this.rect_peq = new RectF[eq.length];
    this.rect_peq = [];
    for (int i = 0; i < eq.length; i++) {
      this.rect_peq.add(RectF());
    }

    for (int var2 = 0; var2 < this.boolean_peq.length; ++var2) {
      this.boolean_peq[var2] = true;
      RectF rect = RectF();
      rect.left = 0;
      rect.top = 0;
      rect.right = 20;
      rect.bottom = 20;
      this.rect_peq[var2] = rect;
    }
  }

  void setPEQDisplay2(int var1, bool var2) {
    this.boolean_peq[var1] = (var2);
  }

  void setPEQDisplay(bool var1) {
    for (int var2 = 0; var2 < this.boolean_peq.length; ++var2) {
      this.boolean_peq[var2] = (var1);
    }
  }

  void setXoverDisplay2(int var1, bool var2) {
    this.boolean_xover?[var1] = var2;
  }

  void setXoverDisplay(bool var1) {
    this.boolean_xover?[1] = var1;
    this.boolean_xover?[0] = var1;
  }

  /// *********start***********/
  void colXover(int width) {
    if (this.line_xover != null) {
      for (int i = 0; i < this.mXover!.length; ++i) {
//            this.colXover(i, width);
        colXover2(i, width);
      }
    }
  }

  void colXover2(int xoverIndex, int width) {
    if (this.line_xover[xoverIndex] == null) {
      return;
    }
    int height = this.mBottom - this.mTop;
    int freq = this.mXover![xoverIndex].toInt();
    int type = this.mXoverType[xoverIndex].toInt();
    bool var6;
    if (xoverIndex == 1) {
      var6 = true;
    } else {
      var6 = false;
    }

//    DrawFunction.cal_point_xover(freq, type, var6, this.line_xover[xoverIndex], false);
    DrawFunction.cal_point_xover(
        freq.toDouble(), type, var6, this.line_xover[xoverIndex]);
//    EqUtil.double2float(this.times, this.mTop + height / 2, this.line_xover[xoverIndex], 60, this.fline_xover[xoverIndex]);
    Equtil.double2float(this.times, (this.mTop + height / 2).toInt(),
        this.line_xover[xoverIndex], 30, this.fline_xover[xoverIndex]);
//    EqUtil.cal_rect(this.rect_xover[xoverIndex], 20, 0, freq, width - 60 - 20, height, 60, this.mTop, 18);
    Equtil.cal_rect(this.rect_xover[xoverIndex], 10, 0, freq, width - 30 - 10,
        height, 30, this.mTop, 18);
  }

  void refreshXover() {
    for (int i = 0; i < this.mXover!.length; ++i) {
//        this.colXover(i, this.getWidth());
      colXover2(i, this.width);
    }

    colOverlay();
//    this.invalidate();
    setNeedsDisplay = true;
  }

  void refreshXover2(int var1) {
    this.drawI = this.mEq!.length + var1;
    //    this.colXover(var1, this.getWidth());
    colXover2(var1, this.width);
//    this.colOverlay();
    colOverlay();
//    this.invalidate();
    setNeedsDisplay = true;
  }

  void setXover(List<double> xover, List<double> xoverType) {
    this.mXover = xover;
    this.mXoverType = xoverType;
//    this.line_xover = new double[xover.length][];
    this.line_xover = [];
    for (int i = 0; i < xover.length; i++) {
      this.line_xover.add([]);
    }
//    this.fline_xover = new float[xover.length][];
    this.fline_xover = [];
    for (int i = 0; i < xover.length; i++) {
      this.fline_xover.add([]);
    }
//    this.boolean_xover = new boolean[xover.length];
    this.boolean_xover = [];
    for (int i = 0; i < xover.length; i++) {
      this.boolean_xover?.add(false);
    }
    this.rect_xover = [];
    for (int i = 0; i < xover.length; i++) {
      this.boolean_xover?[i] = true;

//        [this.boolean_xover.add((YES)];
      RectF rect = RectF();
      rect.left = 0;
      rect.top = 0;
      rect.right = 40;
      rect.bottom = 40;
//        this.rect_xover[i] = rect;
      this.rect_xover.add(rect);
    }
  }
}
